package org.quipu.domain;

import java.io.Serializable;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import javax.persistence.Basic;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import javax.persistence.Table;

@Entity
@Table(name = "BOOK")
@NamedQueries({
    @NamedQuery(name = "Book.findAll", query = "SELECT b FROM Book b"),
    @NamedQuery(name = "Book.findById", query = "SELECT b FROM Book b WHERE b.id=:id"),
    @NamedQuery(name = "Book.findByTitle", query = "SELECT b FROM Book b WHERE b.title=:title")
})
public class Book extends UniqueEntity implements Serializable {

    @Basic(optional = false)
    @Column(name = "TITLE", length = 64, nullable = false)
    private String title;

    @OneToMany(mappedBy = "book", cascade = CascadeType.REMOVE)
    private Collection<BookUser> bookUsers;

    @OneToMany(mappedBy = "book", cascade = CascadeType.REMOVE)
    private Collection<Account> accounts;

    @OneToMany(mappedBy = "book", cascade = CascadeType.REMOVE)
    private Collection<Currency> currencies;

    @OneToMany(mappedBy = "book", cascade = CascadeType.REMOVE)
    private Collection<Category> categories;

    @OneToMany(mappedBy = "book", cascade = CascadeType.REMOVE)
    private Collection<Tag> tags;

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public Collection<BookUser> getBookUsers() {
        return bookUsers;
    }

    public void setBookUsers(Collection<BookUser> bookUsers) {
        this.bookUsers = bookUsers;
    }

    public Collection<Account> getAccounts() {
        return accounts;
    }

    public Collection<Account> getOwnAccounts() {
        Collection<Account> own = new LinkedList<Account>();
        for(Account a: accounts) {
            if(!a.isThirdParty())
                own.add(a);
        }
        return own;
    }

    public Collection<Long> getOwnAccountIds() {
        Collection<Long> ownIds = new LinkedList<Long>();
        for(Account a: accounts) {
            if(!a.isThirdParty())
                ownIds.add(a.getId());
        }
        return ownIds;
    }

    public Collection<Account> getThirdPartyAccounts() {
        Collection<Account> thirdparty = new LinkedList<Account>();
        for(Account a: accounts) {
            if(a.isThirdParty())
                thirdparty.add(a);
        }
        return thirdparty;
    }

    public Collection<Long> getThirdPartyAccountIds() {
        Collection<Long> thirdpartyIds = new LinkedList<Long>();
        for(Account a: accounts) {
            if(a.isThirdParty())
                thirdpartyIds.add(a.getId());
        }
        return thirdpartyIds;
    }

    public void setAccounts(Collection<Account> accounts) {
        this.accounts = accounts;
    }

    public Collection<Currency> getCurrencies() {
        return currencies;
    }

    public void setCurrencies(Collection<Currency> currencies) {
        this.currencies = currencies;
    }

    public Collection<Category> getCategories() {
        return categories;
    }

    public Collection<Category> getCategories(Transaction.Type type) {
        List<Category> typeCategories = new LinkedList<Category>();
        for(Category category: categories) {
            if(type.equals(category.getType()))
                typeCategories.add(category);
        }
        return typeCategories;
    }

    public Collection<Category> getRootCategories(Transaction.Type type) {
        List<Category> typeRootCategories = new LinkedList<Category>();
        for(Category category: categories) {
            if(type.equals(category.getType()) && category.getParentCategory() == null)
                typeRootCategories.add(category);
        }
        return typeRootCategories;
    }

    public void setCategories(Collection<Category> categories) {
        this.categories = categories;
    }

    public boolean containsCategory(String title, Category parent, Transaction.Type type) {
        for (Category category: categories) {
            if(title != null && title.equalsIgnoreCase(category.getTitle())
                && ((parent == null && category.getParentCategory() == null)
                || (parent != null && category.getParentCategory() != null && category.getParentCategory().equals(parent)))
                && type.equals(category.getType()))
                return true;
        }
        return false;
    }

    public Collection<Tag> getTags() {
        return tags;
    }

    public void setTags(Collection<Tag> tags) {
        this.tags = tags;
    }

    public Account findAccount(String title) {
        Account account = null;
        for(Account bookAccount: accounts) {
            if(bookAccount.getTitle().equalsIgnoreCase(title))
                account = bookAccount;
        }
        return account;
    }

    public Currency findCurrency(Long id) {
        Currency currency = null;
        for(Currency bookCurrency: currencies) {
            if(bookCurrency.getId().equals(id))
                currency = bookCurrency;
        }
        return currency;
    }

    public Currency findCurrency(String title) {
        Currency currency = null;
        for(Currency bookCurrency: currencies) {
            if(bookCurrency.getTitle().equalsIgnoreCase(title))
                currency = bookCurrency;
        }
        return currency;
    }

    public Category findCategory(String title, Category parent) {
        Category category = null;
        for(Category bookCategory: categories) {
            if(((parent == null && bookCategory.getParentCategory() == null)|| (parent != null
                && bookCategory.getParentCategory() != null && bookCategory.getParentCategory().equals(parent)))
                && bookCategory.getTitle().equalsIgnoreCase(title))
                category = bookCategory;
        }
        return category;
    }

    public Tag findTag(Long id) {
        Tag tag = null;
        for(Tag bookTag: tags) {
            if(bookTag.getId().equals(id))
                tag = bookTag;
        }
        return tag;
    }

    public Tag findTag(String title) {
        Tag tag = null;
        for(Tag bookTag: tags) {
            if(bookTag.getTitle().equalsIgnoreCase(title))
                tag = bookTag;
        }
        return tag;
    }

    @Override
    public String toString() {
        return "{ id=" + getId() + "; title=" + getTitle() + "; }";
    }
}
